module fetch(
    //clk & rst
    input clk,
    input rst_b,

    //jump
    input [31:0] jump_addr_ctl,
    input jump_ctl,

    //control
    input hold_ctl,
    input clear_ctl,

    //io with inst mem
    input [31:0] inst_if_ctl,
    output reg [31:0] pc_if_pre,
    output wire pc_req_if_pre,

    //io with decoder
    output reg [31:0] pc_if,
    output  [31:0] inst_if 
);

assign pc_req_if_pre = 1'b1;

always @(posedge clk or negedge rst_b) begin
  if(~rst_b)
    pc_if_pre <= 32'd0;
  else if(jump_ctl)
    pc_if_pre <= jump_addr_ctl;
  else if(hold_ctl)
    pc_if_pre <= pc_if_pre;
  else if(clear_ctl)
    pc_if_pre <= 32'd0;
  else
    pc_if_pre <= pc_if_pre + 32'd4;
end

always @(posedge clk or negedge rst_b) begin
  if(~rst_b) begin
    pc_if   <= 32'd0;
  end
  else if(hold_ctl) begin
    pc_if   <= pc_if;
  end
  else if(clear_ctl) begin
    pc_if   <= 32'd0;
  end
  else begin
    pc_if   <= pc_if_pre;
  end
end

reg clear_ctl_d,hold_ctl_d;
always @(posedge clk or negedge rst_b) begin
  if(~rst_b) begin
    clear_ctl_d <= 1'b0;
    hold_ctl_d  <= 1'b0;
  end
  else begin
    clear_ctl_d <= clear_ctl;
    hold_ctl_d  <= hold_ctl;
  end
end

wire hold_ctl_on_str = hold_ctl & ~hold_ctl_d;
reg [31:0] inst_if_ctl_hold;
always @(posedge clk or negedge rst_b) begin
  if(~rst_b)
    inst_if_ctl_hold <= 32'd0;
  else if(hold_ctl_on_str)
    inst_if_ctl_hold <= inst_if_ctl;
end


assign inst_if = hold_ctl_d ? inst_if_ctl_hold : (clear_ctl_d ? 32'd0 : inst_if_ctl);

endmodule
